Skip to content

src: enable V8's WASM trap handlers - #27246

Merged
devsnek merged 1 commit into
nodejs:masterfrom
devsnek:enable-wasm-trap-handler
May 16, 2019
Merged

devsnek merged 1 commit into
nodejs:masterfrom
devsnek:enable-wasm-trap-handler

Conversation

@devsnek

@devsnek devsnek commented Apr 15, 2019 •

Copy link
Copy Markdown
Member

This uses SIGSEGV handlers to catch WASM out of bound (OOB) memory
accesses instead of inserting OOB checks inline, resulting in a 25%-30%
speed increase.

Note that installing a custom SIGSEGV handler will break this, resulting
in potentially scary behaviour. Users should use node::RegisterSignalHandler instead.

Refs: #14927

Closes #14927

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • commit message follows commit guidelines

@nodejs-github-bot

ghost commented Apr 15, 2019

Copy link
Copy Markdown
Collaborator

@nodejs-github-bot nodejs-github-bot added the c++ Issues and PRs that require attention from people who are familiar with C++. label Apr 15, 2019
@devsnek
devsnek force-pushed the enable-wasm-trap-handler branch from 2aa0fb8 to 5402f28 Compare April 15, 2019 21:18
@addaleax

ghost commented Apr 15, 2019

Copy link
Copy Markdown
Member

My gut feeling would be that @ofrobots’s comment in #14927 (comment) is a good approach – using our own signal handler, and providing a public C++ API for forwarding that to addons/embedders? That would mean that those would not have to carry the responsibility of integrating with V8’s APIs.

I’d say this is semver-major because of the conflicts with existing published versions of segfault-handler – do you agree? If yes, then I’m happy with any approach, because we should have more than enough time to update that package.

@devsnek devsnek added the semver-major PRs that contain breaking changes and should be released in the next major version. label Apr 15, 2019
@devsnek

ghost commented Apr 15, 2019 •

Copy link
Copy Markdown
Member Author

@addaleax we already have node::RegisterSignalHandler, i guess i could set this up with that, although i think this then becomes uh... not platform independent.

we'll need to add a bunch of platform specific switches for calling TryWasmTrapHanderPosix vs TryWasmTrapHandlerWin but if that complexity is okay then we can go for it.

@devsnek
devsnek force-pushed the enable-wasm-trap-handler branch 3 times, most recently from ea0ade9 to ab9a5b7 Compare April 15, 2019 22:00
@devsnek

ghost commented Apr 15, 2019

Copy link
Copy Markdown
Member Author

@addaleax set up to use RegisterSignalHandler, unfortunately we only have that for posix atm, so maybe we can expand to win in the future? (although i don't think people on windows are expecting great performance anyway 🤷‍♂️)

@devsnek
devsnek force-pushed the enable-wasm-trap-handler branch 2 times, most recently from 7c3fee8 to 0865e93 Compare April 15, 2019 22:18
@addaleax

ghost commented Apr 15, 2019

Copy link
Copy Markdown
Member

@devsnek Yeah, we’d need to find some common API (or expose 2 variants) for both Windows and POSIX; and maybe find some API constraints, e.g. what happens if it is called multiple times, is the registering function threadsafe, etc. and document that

@devsnek devsnek added v8 engine Issues and PRs related to the V8 dependency. wasm Issues and PRs related to WebAssembly. labels Apr 16, 2019
Comment thread src/node.cc Outdated
@devsnek
devsnek force-pushed the enable-wasm-trap-handler branch from 0865e93 to a244828 Compare April 16, 2019 03:39
Comment thread src/node.cc Outdated

ghost Apr 16, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you put this into the per_process namespace and make it static?

Comment thread src/node.cc Outdated
Comment thread src/node.cc Outdated
Comment thread src/node.cc Outdated
Comment thread src/node.cc Outdated
Comment thread src/node.cc Outdated
Comment thread src/node.cc Outdated
@bnoordhuis

ghost commented Apr 16, 2019

Copy link
Copy Markdown
Member

Sorry, I forgot to mention something important: you must re-raise the SIGSEGV when V8 doesn't handle it and there's no other handler for it.

@devsnek
devsnek force-pushed the enable-wasm-trap-handler branch 2 times, most recently from 94fbe09 to d05e688 Compare April 20, 2019 17:56
@devsnek
devsnek force-pushed the enable-wasm-trap-handler branch from d05e688 to c7d11fe Compare April 30, 2019 05:29
Comment thread src/node.cc Outdated

ghost Apr 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocker, just an observation, but I expect that's no longer relevant for the freebsd versions we support.

ghost Apr 30, 2019

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nodejs/platform-freebsd can anyone confirm or deny?

ghost Apr 30, 2019

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bnoordhuis do you know if there's any more background/detail on the issue?

@kostikbel any insight? The referenced comment is:

  // FreeBSD has a nasty bug with SA_RESETHAND reseting the SA_SIGINFO, that is
  // in turn set for a libthr wrapper. This leads to a crash.
  // Work around the issue by manually setting SIG_DFL in the signal handler

ghost Apr 30, 2019 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my copy of POSIX 1003.1-2017 AKA SUSv7:

SA_RESETHAND If set, the disposition of the signal shall be reset to SIG_DFL and the SA_SIGINFO flag shall be cleared on entry to the signal handler.

And we do exactly that. Am I reading right that this behavior causes some troubles, when combined with libthr ? Can you give a minimal example ?

ghost May 1, 2019 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@emaste @kostikbel The bug report is nodejs/node-v0.x-archive#9326, triage starts in nodejs/node-v0.x-archive#9326 (comment).

I'm reasonably sure that bug was fixed in fbsd 11 but you probably know for sure, @kostikbel, since you authored the fix.

ghost May 1, 2019

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so should this comment (and possibly some code) removed ? Since I believe all supported FreeBSD versions have the SA_RESETHAND | SA_SIGINFO fix.

ghost May 1, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds about right (removing code & comment.) I've opened #27515 to track it.

Comment thread src/node.cc Outdated
@devsnek

ghost commented Apr 30, 2019 •

Copy link
Copy Markdown
Member Author

@bnoordhuis do you know why this compiles fine on macos but has issues finding those atomic symbols on the linux build?

@bnoordhuis

ghost commented May 1, 2019

Copy link
Copy Markdown
Member

Reproducing here because scrolling trough Travis really is quite horrid:

Details
/home/travis/build/nodejs/node/out/Release/obj.target/libnode/src/node.o: In function `node::TrapWebAssemblyOrContinue(int, siginfo_t*, void*) [clone .part.36]':
node.cc:(.text+0xce): undefined reference to `__atomic_load'
/home/travis/build/nodejs/node/out/Release/obj.target/libnode/src/node.o: In function `node::RegisterSignalHandler(int, void (*)(int, siginfo_t*, void*), bool, sigaction*)':
node.cc:(.text+0x2484): undefined reference to `__atomic_exchange'
collect2: error: ld returned 1 exit status
cctest.target.mk:226: recipe for target '/home/travis/build/nodejs/node/out/Release/cctest' failed
make[1]: *** [/home/travis/build/nodejs/node/out/Release/cctest] Error 1
make[1]: *** Waiting for unfinished jobs....
/home/travis/build/nodejs/node/out/Release/obj.target/libnode/src/node.o: In function `node::TrapWebAssemblyOrContinue(int, siginfo_t*, void*) [clone .part.36]':
node.cc:(.text+0xce): undefined reference to `__atomic_load'
/home/travis/build/nodejs/node/out/Release/obj.target/libnode/src/node.o: In function `node::RegisterSignalHandler(int, void (*)(int, siginfo_t*, void*), bool, sigaction*)':
node.cc:(.text+0x2484): undefined reference to `__atomic_exchange'
collect2: error: ld returned 1 exit status

I'm going to guess that gcc doesn't know how to lower the __atomic_load and __atomic_exchange builtins for compound types (i.e., struct sigaction) and just re-emits them as library calls.

If you switch to function pointers, the problem should hopefully go away.

@richardlau

ghost commented May 1, 2019

Copy link
Copy Markdown
Member

Or maybe link to libatomic? https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65756#c1

@nodejs-github-bot

ghost commented May 16, 2019

Copy link
Copy Markdown
Collaborator

@devsnek devsnek added author ready PRs with CI started, the required approvals, and no outstanding review comments. and removed tsc-agenda Issues and PRs to discuss during Technical Steering Committee meetings. labels May 16, 2019
This uses SIGSEGV handlers to catch WASM out of bound (OOB) memory
accesses instead of inserting OOB checks inline, resulting in a 25%-30%
speed increase.

Note that installing a custom SIGSEGV handler will break this, resulting
in potentially scary behaviour.

Refs: nodejs#14927

PR-URL: nodejs#27246
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
@devsnek
devsnek force-pushed the enable-wasm-trap-handler branch from 3cdac98 to 70c7686 Compare May 16, 2019 17:33
@devsnek

ghost commented May 16, 2019

Copy link
Copy Markdown
Member Author

landed in 70c7686

@devsnek
devsnek merged commit 70c7686 into nodejs:master May 16, 2019
@devsnek
devsnek deleted the enable-wasm-trap-handler branch May 16, 2019 17:35
@BridgeAR

ghost commented May 21, 2019

Copy link
Copy Markdown
Member

@devsnek @addaleax is there a way to backport this PR with a compatibility patch to remove the breaking change? It would already be helpful if e.g. 50% of the code would be backported.

@addaleax

ghost commented May 21, 2019

Copy link
Copy Markdown
Member

@BridgeAR I guess it would be possible to backport this in a non-breaking manner, but it should not be released without #27775 as well

@BridgeAR

ghost commented May 21, 2019

Copy link
Copy Markdown
Member

@addaleax sounds good 👍. Would you be willing to open the backport after #27775 landed?

@devsnek devsnek added the notable-change PRs with changes that should be highlighted in changelogs. label Sep 9, 2019
@devsnek

ghost commented Sep 9, 2019

Copy link
Copy Markdown
Member Author

Notable change:

This speeds up memory operations for WASM by around 25-30%. However, native code must now install the SIGSEGV signal handlers using node::RegisterSignalHandler.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author ready PRs with CI started, the required approvals, and no outstanding review comments. c++ Issues and PRs that require attention from people who are familiar with C++. notable-change PRs with changes that should be highlighted in changelogs. semver-major PRs that contain breaking changes and should be released in the next major version. v8 engine Issues and PRs related to the V8 dependency. wasm Issues and PRs related to WebAssembly.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WebAssembly OOB Signal Handlers + Node